#能够动态(循环一次计算一次返回一次)提供数据的可迭代对象


#1 生成器函数


def my_range(stop):
    num = 0
    while num < stop:
        yield num
        num += 1

for item in my_range(5):
    print(item)
# 0
# 1
# 2
# 3
# 4

iter_obj = my_range(5).__iter__()
while True:
    try:
        num = iter_obj.__next__()
        print(num)
    except StopIteration:
        break
# 0
# 1
# 2
# 3
# 4


def find_even_number(listn_num):
    for item in listn_num:
        if item % 2 == 0:
            yield item

for n in find_even_number([43,43,54,56,76,87,98]):
    print(n)

# 54
# 56
# 76
# 98


#练习2：定义函数,在列表中找出所有数字

def my_filter(obj,fn):
    for item in obj:
        if fn(item):
            yield item
def _fn(item):
    return (isinstance(item,int) or isinstance(item,float)) and (not isinstance(item,bool))
numlist = my_filter([43,"悟空",True,56,"八戒",87.5,98],_fn)

for num in numlist:
    print(num)



def _fn02(item):
    return type(item)==int or type(item)==float
numlist = my_filter([43,"悟空",True,56,"八戒",87.5,98],_fn02)

for num in numlist:
    print(num)



#2 内置生成器


#2.1 枚举函数enumerate


list02 = [52,52,85,45,21,32]

# 读取数据

for item in list02:
    print(item)

# 52
# 52
# 85
# 45
# 21
# 32

#修改数据

for i in range(len(list02)):
    if list02[i] % 2 == 2:
        list02[i] += 1
print(list02)
#[52, 52, 85, 45, 21, 32]


for index,item in enumerate(list02):
    if item % 2 == 0:
        list02[index] += 1
print(list02)
#[53, 53, 85, 45, 21, 33]


#2.2 zip
#作用：将多个可迭代对象中对应的元素组合成一个个元组，
# 生成的元组个数由最小的可迭代对象决定。

list_name = ["悟空", "八戒", "沙僧"]
list_age = [22, 26, 25]

for item in zip(list_name,list_age):
    print(item)

# ('悟空', 22)
# ('八戒', 26)
# ('沙僧', 25)


# 应用:矩阵转置

map = [
    [2, 0, 0, 2],
    [4, 2, 0, 2],
    [2, 4, 2, 4],
    [0, 4, 0, 4]
]

new_map = []
for item in zip(map[0],map[1],map[2],map[3]):
    new_map.append(list(item))
print(new_map)
#[[2, 4, 2, 0], [0, 2, 4, 4], [0, 0, 2, 0], [2, 2, 4, 4]]


new_map02 = []
for item in zip(*map):
    new_map02.append(item)
print(new_map)
#[[2, 4, 2, 0], [0, 2, 4, 4], [0, 0, 2, 0], [2, 2, 4, 4]]

new_map03 = [list(item) for item in zip(*map)]
print(new_map03)
#[[2, 4, 2, 0], [0, 2, 4, 4], [0, 0, 2, 0], [2, 2, 4, 4]]



#练习：将两个列表合并为一个字典

list_student_name = ["悟空", "八戒", "白骨精"]
list_student_age = [28, 25, 36]

dict01 = {*[item for item in zip(list_student_name,list_student_age)]}
print(dict01)



#4.3 生成器表达式

#(1) 定义：用推导式形式创建生成器对象。

#(2) 语法：
#变量 = (表达式 for 变量 in 可迭代对象 if 条件)

# 生成器表达式的优点之一是它们在内存使用方面更加高效，
# 因为它们是惰性计算的，只有在需要时才会生成值，
# 而不是一次性生成所有值。
# 这使得生成器表达式特别适合处理大型数据集或无限序列。

#练习1：使用生成器表达式在列表中获取所有字符串.

list01 = [43, "a", 5, True, 6, 7, 89, 9, "b"]

iterobj = (item for item in list01 if isinstance(item,str))
print(iterobj)

# for item in iterobj:
#     print(item)

print(iterobj.__next__())#b
print(iterobj.__next__())#a
#print(iterobj.__next__())# StopIteration 无元素


#练习2：在列表中获取所有整数,并计算它的平方.


iterobj2 = (item**2 for item in list01 if isinstance(item,int) and not isinstance(item,bool))
print([item for item in iterobj2])
#[1849, 25, 36, 49, 7921, 81]